﻿using LaGraderia.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LaGraderia.Dades
{
    public class Contexte : DbContext
    {

        public DbSet<Usuari> Usuaris { get; set; }
        public DbSet<Jugador> Jugadors { get; set; }
        public DbSet<Equip> Equips { get; set; }
        public DbSet<Partit> Partits { get; set; }
        public DbSet<Competicio> Competicions { get; set; }

        #region Creacio de la BD

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

            base.OnModelCreating(modelBuilder);

            // -------------------------------------------------
            // ----------------  UserProfile -----------------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Usuari> Usuari;
            Usuari = modelBuilder.Entity<Usuari>();
            //Taula
            Usuari.ToTable("Usuaris");
             //Clau primaria
            Usuari.HasKey(j => j.IdUsuari);
            Usuari.Property(j => j.IdUsuari).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            //Atributs
            Usuari.Property(j => j.NomUsuari).IsRequired().HasMaxLength(25);
            //Estat
            Usuari.Ignore(j => j.Estat);
            
            // -------------------------------------------------
            // ----------------  Jugador -----------------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Jugador> Jugador;
            Jugador = modelBuilder.Entity<Jugador>();
            //Taula
            Jugador.ToTable("Jugadors");
            //Clau primaria
            Jugador.HasKey(j => j.IdJugador);
            Jugador.Property(j => j.IdJugador).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            //Atributs
            Jugador.Property(j => j.Nom).IsRequired().HasMaxLength(25);
            Jugador.Property(j => j.Cognom1).IsRequired().HasMaxLength(25);
            Jugador.Property(j => j.Cognom2).HasMaxLength(25);
            Jugador.Property(j => j.Email).IsRequired().HasMaxLength(50);
            Jugador.Property(j => j.Pala).HasMaxLength(50);
            Jugador.Property(j => j.MaDreta).IsRequired();
            Jugador.Property(j => j.LlocDret).IsRequired();
            //Estat
            Jugador.Ignore(j => j.Estat);
            //Relacions

            // -------------------------------------------------
            // ----------------  Equip   -----------------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Equip> Equip;
            Equip = modelBuilder.Entity<Equip>();
            //Taula
            Equip.ToTable("Equips");
            //Clau primaria
            Equip.HasKey(e => e.IdEquip);
            Equip.Property(e => e.IdEquip).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            //Atributs
            Equip.Property(e => e.Nom).HasMaxLength(25);
            //Estat
            Equip.Ignore(e => e.Estat);
            //Relacions
            Equip.HasMany(e => e.Jugadors).WithMany(j => j.Equips).Map(mc =>
            {
                mc.ToTable("JugadorEquip");
                mc.MapLeftKey("IdEquip");
                mc.MapRightKey("IdJugador");
            });


            // -------------------------------------------------
            // ----------------  Estad Jugador   --------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<EstadJugador> EstadJugador;
            EstadJugador = modelBuilder.Entity<EstadJugador>();
            //Taula
            EstadJugador.ToTable("EstadJugadors");
            //Clau primaria
            EstadJugador.HasKey(e => new { e.IdJugador, e.Temporada });
            //Atributs
            //Estat
            EstadJugador.Ignore(e => e.Estat);
            //Relacions
            EstadJugador.HasRequired(e => e.Jugador).WithMany(j => j.EstadsJugadors).HasForeignKey(e => e.IdJugador);


            // -------------------------------------------------
            // ----------------  Estad Equip   -----------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<EstadEquip> EstadEquip;
            EstadEquip = modelBuilder.Entity<EstadEquip>();
            //Taula
            EstadEquip.ToTable("EstadEquips");
            //Clau primaria
            EstadEquip.HasKey(e => new { e.IdEquip, e.Temporada });
            //Atributs
            //Estat
            EstadEquip.Ignore(e => e.Estat);
            //Relacions
            EstadEquip.HasRequired(e => e.Equip).WithMany(j => j.EstadsEquip).HasForeignKey(e => e.IdEquip);


            // -------------------------------------------------
            // ----------------  Competicio  -------------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Competicio> Competicio;
            Competicio = modelBuilder.Entity<Competicio>();
            //Taula
            Competicio.ToTable("Competicions");
            //Clau primaria           
            Competicio.HasKey(c => c.IdCompeticio);
            Competicio.Property(c => c.IdCompeticio).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            //Atributs
            Competicio.Property(c => c.Nom).IsRequired().HasMaxLength(50);
            //Estat
            Competicio.Ignore(c => c.Estat);
            //Relacions
            Competicio.HasMany(c => c.Equips).WithMany(e => e.Competicions).Map(mc =>
            {
                mc.ToTable("CompeticioEquip");
                mc.MapLeftKey("IdCompeticio");
                mc.MapRightKey("IdEquip");
            });

            //// -------------------------------------------------
            //// ----------------  Lliga  ------------------------
            //// -------------------------------------------------
            //System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Lliga> Lliga;
            //Lliga = modelBuilder.Entity<Lliga>();
            ////Taula
            //Lliga.ToTable("Lligues");
            ////Clau primaria
            ////Atributs
            //Lliga.Property(l => l.IdTorneig).IsOptional();
            ////Estat
            ////Relacions
            //Lliga.HasOptional(l => l.Torneig).WithMany(t => t.Lligues).HasForeignKey(l => l.IdTorneig);

            //// -------------------------------------------------
            //// ----------------  Torneig  ----------------------
            //// -------------------------------------------------
            //System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Torneig> Torneig;
            //Torneig = modelBuilder.Entity<Torneig>();
            ////Taula
            //Torneig.ToTable("Tornejos");
            ////Clau primaria
            ////Atributs
            ////Estat
            ////Relacions

            // -------------------------------------------------
            // ----------------  Etapa  ------------------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Etapa> Etapa;
            Etapa = modelBuilder.Entity<Etapa>();
            //Taula
            Etapa.ToTable("Etapes");
            //Clau primaria
            Etapa.HasKey(e => new { e.IdCompeticio, e.NumEtapa });
            //Atributs
            Etapa.Property(e => e.NumEtapa).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            //Estat
            Etapa.Ignore(e => e.Estat);
            //Relacions
            Etapa.HasRequired(e => e.Competicio).WithMany(c => c.Etapes).HasForeignKey(e => e.IdCompeticio);

            // -------------------------------------------------
            // ----------------  Partit   ---------------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Partit> Partit;
            Partit = modelBuilder.Entity<Partit>();
            //Taula
            Partit.ToTable("Partits");
            //Clau primaria
            Partit.HasKey(p => new { p.IdCompeticio, p.NumEtapa, p.IdPartit });
            Partit.Property(p => p.IdPartit).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            //Atributs
            Partit.Property(p => p.Data).IsOptional();
            Partit.Property(p => p.DataModificacio).IsRequired();
            Partit.Property(p => p.UsuariModificacio).IsRequired().HasMaxLength(50);
            Partit.Property(p => p.IdEquipVisitant).IsOptional();
            Partit.Property(p => p.IdEquipLocal).IsOptional();
            //Estat
            Partit.Ignore(p => p.Estat);
            //Relacions
            Partit.HasRequired(p => p.Etapa).WithMany(e => e.Partits).HasForeignKey(p => new { p.IdCompeticio, p.NumEtapa });
            Partit.HasOptional(p => p.EquipLocal).WithMany(e => e.PartitsLocal).HasForeignKey(p => p.IdEquipLocal);
            Partit.HasOptional(p => p.EquipVisitant).WithMany(e => e.PartitsVisitant).HasForeignKey(p => p.IdEquipVisitant);



            // -------------------------------------------------
            // ----------------  Resultat   --------------------
            // -------------------------------------------------
            System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Resultat> Resultat;
            Resultat = modelBuilder.Entity<Resultat>();
            //Taula
            Resultat.ToTable("Resultats");
            //Clau primaria
            Resultat.HasKey(r => new { r.IdCompeticio, r.NumEtapa, r.IdPartit, r.NumResultat });
            //Atributs
            Resultat.Property(r => r.PuntsLocal).IsRequired();
            Resultat.Property(r => r.PuntsVisitant).IsRequired();
            //Estat
            Resultat.Ignore(r => r.Estat);
            //Relacions
            Resultat.HasRequired(r => r.Partit).WithMany(p => p.Resultats).HasForeignKey(r => new { r.IdCompeticio, r.NumEtapa, r.IdPartit });


        }

        #endregion
        
        #region Actualitzacio de la bd

        public void ActualitzaEntitat<TipusEntitat>(TipusEntitat entitat)
            where TipusEntitat : ObjecteAmbEstat
        {
            this.Set<TipusEntitat>().Add(entitat);
            this.ActualitzaEstatContexte();
            this.SaveChanges();
            this.AcceptaCanvis();
        }

        private void ActualitzaEstatContexte()
        {
            foreach (System.Data.Entity.Infrastructure.DbEntityEntry<ObjecteAmbEstat> entradaEntitat in this.ChangeTracker.Entries<ObjecteAmbEstat>())
            {
                System.Data.EntityState state;

                switch (entradaEntitat.Entity.Estat)
                {
                    case EnumEstat.Afegit :
                        state = System.Data.EntityState.Added;
                        break;
                    case EnumEstat.Modificat :
                        state = System.Data.EntityState.Modified;
                        break;
                    case EnumEstat.Eliminat :
                        state = System.Data.EntityState.Deleted;
                        break;
                    default:
                        state = System.Data.EntityState.Unchanged;
                        break;

                }

                entradaEntitat.State = state;

            }
        }

        private void AcceptaCanvis()
        {
            foreach (System.Data.Entity.Infrastructure.DbEntityEntry<ObjecteAmbEstat> entradaEntitat in this.ChangeTracker.Entries<ObjecteAmbEstat>())
            {
                entradaEntitat.Entity.Estat = EnumEstat.NoModificat;
            }
               
        }
        
        #endregion

    }
}
